package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageBean;
import com.zzyl.constant.CacheConstants;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliyunIotProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.vo.DevicePropertyStatusVo;
import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import com.zzyl.vo.QueryThingModelVo;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.assertj.core.util.Lists;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

@Service
@RequiredArgsConstructor
public class DeviceServiceImpl implements DeviceService {
    final DeviceMapper deviceMapper;
    final Client client;
    final AliyunIotProperties aliyunIotProperties;
    final StringRedisTemplate stringRedisTemplate;


    /**
     * 同步互联网平台产品列表
     */
    @Override
    @SneakyThrows   //lombok插件，可以不用try catch
    public void syncProductList() {
        //1.查找Iot平台的产品列表
        QueryProductListRequest request = new QueryProductListRequest();
        request.setCurrentPage(1);
        request.setPageSize(200);
        request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());
        //1.1执行请求，发送请求
        QueryProductListResponse response = client.queryProductList(request);
        if (!response.body.success) {
            throw new BaseException(BasicEnum.IOT_LIST_PRODUCT_ERROR);
        }
        //1.2将结果拷贝到新的List中,并转换为ProductVo
        List<ProductVo> productVoList = BeanUtil.copyToList(response.body.data.list.productInfo, ProductVo.class);

        //2.将产品列表保存到redis中
        stringRedisTemplate.opsForValue().set(CacheConstants.IOT_ALL_PRODUCT, JSON.toJSONString(productVoList));
    }

    /**
     * 查询所有产品列表
     */
    @Override
    public List<ProductVo> allProduct() {
        //从缓存中获取数据
        String jsonStr = stringRedisTemplate.opsForValue().get(CacheConstants.IOT_ALL_PRODUCT);
        //如果为空，返回空集合
        if (StrUtil.isEmpty(jsonStr)) {
            return Collections.emptyList();
        }
        //转换数据，并返回
        return JSONUtil.toList(jsonStr, ProductVo.class);
    }

    /**
     * 注册设备
     *
     * @param
     */
    @Override
    @SneakyThrows
    public void registerDevice(DeviceDto dto) {
        String iotInstanceId = aliyunIotProperties.getIotInstanceId(); // iot实例id
        String ioTId; // iot设备id
        //检验设备名称是否重复
        int count = deviceMapper.countByDeviceName(dto.getDeviceName());
        if (count > 0) {
            throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);
        }
        // 添加设备到iot平台
        try {
            RegisterDeviceRequest request = dto.getRegisterDeviceRequest();
            request.setIotInstanceId(iotInstanceId);
            RegisterDeviceResponse response = client.registerDevice(request);
            if (!response.body.success || response.body.data == null) {
                throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
            }
            ioTId = response.body.data.iotId;//获取设备id
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }

        // 保存设备信息到数据库
        try {
            Device device = BeanUtil.toBean(dto, Device.class);
            device.setIotId(ioTId);
            deviceMapper.insert(device);
        } catch (Exception e) {
            DeleteDeviceRequest deleteDeviceRequest = new DeleteDeviceRequest();
            deleteDeviceRequest.setIotInstanceId(iotInstanceId);
            deleteDeviceRequest.setIotId(ioTId);
            client.deleteDevice(deleteDeviceRequest);
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }
    }

    /**
     * 分页查询设备
     *
     * @param dto
     */
    @Override
    public PageBean<DeviceVo> pageQueryDevice(DevicePageQueryDto dto) {
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        Page<DeviceVo> page = deviceMapper.selectPage(dto);
        return PageBean.of(page, DeviceVo.class);
    }

    /**
     * 查询设备详情
     *
     * @param request
     */
    @Override
    @SneakyThrows
    public DeviceVo queryDeviceDetail(QueryDeviceDetailRequest request) {
        //1.根据iotId查询设备信息
        request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());

        QueryDeviceDetailResponse response = client.queryDeviceDetail(request);

        //2.根据iotId查询产品信息
        DeviceVo deviceVo = deviceMapper.selectByIotId(request.getIotId());

        //3.将产品信息和设备信息合并
        BeanUtil.copyProperties(response.body.data, deviceVo);

        return deviceVo;


    }

    /**
     * 查询设备物模型状态
     *
     * @param request
     */
    @Override
    @SneakyThrows
    public DevicePropertyStatusVo queryDevicePropertyStatus(QueryDevicePropertyStatusRequest request) {
        request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());
        QueryDevicePropertyStatusResponse response = client.queryDevicePropertyStatus(request);
        DevicePropertyStatusVo vo = BeanUtil.toBean(response.body.data, DevicePropertyStatusVo.class);
        //将心率放在前面,其他按照属性名排序，集合中的元素按照属性名排序
        vo.list.getPropertyStatusInfo().sort((o1, o2) -> StrUtil.equals(o1.getIdentifier(), "HeartRate") ? -1 : 1);
        return vo;

    }

    /**
     * 修改设备备注名称
     *
     * @param deviceDto
     */
    @Override
    @Transactional
    public void updateDevice(DeviceDto deviceDto) {
        //检验数据库是否存在设备
        Device dbDevice = deviceMapper.selectByPrimaryKey(deviceDto.getId());
        if (ObjectUtil.isEmpty(dbDevice)) {
            throw new BaseException(BasicEnum.DEVICE_NOT_EXIST);
        }

        //更新数据库中设备信息
        try {
            //将dto转换为pojo
            Device device = BeanUtil.toBean(deviceDto, Device.class);
            //判断位置类型：0随身设备，1固定设备        如果是随身设备，将物理位置设为-1
            if (NumberUtil.equals(device.getLocationType(), 0)) {
                device.setPhysicalLocationType(-1);//物理位置类型 0楼层 1房间 2床位 -1随身设备
            }
            deviceMapper.updateByPrimaryKeySelective(device);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }

        //调用物联网接口，更新云服务设备信息
        try {
            //创建请求对象
            BatchUpdateDeviceNicknameRequest request = new BatchUpdateDeviceNicknameRequest();
            //设置iot实例id
            request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());
            //将dto中的数据拷贝到请求对象中
            BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo nicknameInfo =
                    BeanUtil.toBean(deviceDto, BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo.class);
            //设置请求对象信息
            request.setDeviceNicknameInfo(Lists.newArrayList(nicknameInfo));
            //发送请求
            BatchUpdateDeviceNicknameResponse response = client.batchUpdateDeviceNickname(request);
            if (!Boolean.TRUE.equals(response.body.success)) {
                throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
            }
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }

    }

    /**
     * 删除设备
     *
     * @param request
     */
    @Override
    @Transactional
    public void deleteDevice(DeleteDeviceRequest request) {
        request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());
        DeleteDeviceResponse response;

        try {
            deviceMapper.deleteByIotId(request.getIotId());
            response = client.deleteDevice(request);
            if (!response.body.success) {
                throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
            }
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }

    }

    /**
     * 查看指定产品的物模型数据
     *
     * @param request
     */
    @Override
    @SneakyThrows
    public QueryThingModelVo queryThingModelPublished(QueryThingModelPublishedRequest request) {
        request.setIotInstanceId(aliyunIotProperties.getIotInstanceId());
        QueryThingModelPublishedResponse response;
        try {
            response = client.queryThingModelPublished(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
        }
        if (!response.body.success || response.body.data == null) {
            throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
        }
        QueryThingModelPublishedResponseBody.QueryThingModelPublishedResponseBodyData data = response.getBody().getData();

        QueryThingModelVo queryThingModelVo = new QueryThingModelVo();
        BeanUtil.copyProperties(data, queryThingModelVo, CopyOptions.create().ignoreNullValue());
        return queryThingModelVo;
    }


}


